package com.capgemini.cn.authority.core.authentication;

import com.capgemini.cn.authority.core.security.SecurityProfile;
import lombok.Setter;
import org.pac4j.core.context.WebContext;
import org.pac4j.core.credentials.UsernamePasswordCredentials;
import org.pac4j.core.credentials.authenticator.Authenticator;
import org.pac4j.core.exception.CredentialsException;
import org.pac4j.core.exception.HttpAction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.web.context.ContextLoader;

/**
 * <p>用户登录认证器，通过用户名和密码来启动校验程序</p>
 * Created at 2017/8/30
 *
 * @author Andriy
 */
@Component(value = UserAuthenticator.COMPONENT_NAME)
public class UserAuthenticator implements Authenticator<UsernamePasswordCredentials> {

    public static final String COMPONENT_NAME = "userAuthenticator";
    private static final Logger LOGGER = LoggerFactory.getLogger(UserAuthenticator.class);

    @Autowired(required = false)
    @Setter
    private UserValidateProtocol userValidateProtocol;

    @Override
    public void validate(UsernamePasswordCredentials credentials, WebContext context) throws HttpAction, CredentialsException {
        boolean result;
        Assert.notNull(credentials, "参数UsernamePasswordCredentials为Null，不能正常处理登录验证逻辑！");
        if (ObjectUtils.isEmpty(this.userValidateProtocol))   // 如果没有自动注入登录验证接口的实现类，则手动获取默认的登录验证实现类
            this.userValidateProtocol = ContextLoader.getCurrentWebApplicationContext().getBean(DefaultUserValidate.class);
        // 执行登录验证逻辑
        result = this.userValidateProtocol.validate(credentials.getUsername(), credentials.getPassword());
        // 判断登录验证结果
        if (!result) {
            final String errorMsg = "用户" + credentials.getUsername() + "未获得合法授权或未登录！";
            LOGGER.warn(errorMsg);
            throw HttpAction.forbidden(errorMsg, context);
        } else {
            SecurityProfile profile = new SecurityProfile();
            profile.setId(credentials.getUsername());
            profile.setClientName(credentials.getClientName());
            credentials.setUserProfile(profile);
        }
    }
}
